﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Devonline.AspNetCore;

/// <summary>
/// 附件及文件操作类服务
/// </summary>
/// <typeparam name="TDbContext">数据库上下文</typeparam>
/// <typeparam name="TAttachment">附件数据类型</typeparam>
/// <typeparam name="TKey">主键类型</typeparam>
public interface IAttachmentService<TDbContext, TAttachment, TKey>
    where TDbContext : DbContext
    where TAttachment : class, IAttachment<TKey>
    where TKey : IConvertible
{
    /// <summary>
    /// 获取并返回文件名指向的物理文件
    /// </summary>
    /// <param name="fileName">文件名</param>
    /// <returns></returns>
    IActionResult GetFile(string fileName);
    /// <summary>
    /// 文件下载, 提供类似于文件夹目录结构的访问方式进行下载
    /// 形如 2020-01-01/xxx.jpg
    /// </summary>
    /// <param name="fileName">文件名</param>
    /// <param name="filePath">文件路径</param>
    /// <returns></returns>
    Task<TAttachment?> GetAttachmentAsync(string? fileName, string? filePath = null);
    /// <summary>
    /// 获取附件对应的文件, 适用于文件下载
    /// 形如 2020-01-01/xxx.jpg
    /// </summary>
    /// <param name="fileName">文件名</param>
    /// <param name="filePath">文件路径</param>
    /// <returns></returns>
    Task<IActionResult> GetAttachmentFileAsync(string? fileName, string? filePath = null);
    /// <summary>
    /// 获取文件, 按业务类型和业务主键获取
    /// </summary>
    /// <param name="businessType">业务类型</param>
    /// <param name="businessKey">业务主键</param>
    /// <returns></returns>
    Task<IEnumerable<TAttachment>?> GetAttachmentsAsync(string? businessType = null, TKey? businessKey = default);

    /// <summary>
    /// 单个文件上传
    /// </summary>
    /// <param name="file"></param>
    /// <returns></returns>
    Task<UploadResult<TAttachment, TKey>> UploadAsync(IFormFile? file = null);
    /// <summary>
    /// 批量文件上传
    /// </summary>
    /// <param name="files"></param>
    /// <returns></returns>
    Task<IEnumerable<UploadResult<TAttachment, TKey>>> UploadAsync(IEnumerable<IFormFile>? files = null);

    /// <summary>
    /// 删除附件物理文件, 请在附件相关操作的事物提交之后执行此方法
    /// </summary>
    /// <param name="files">待删除的文件</param>
    void Delete(IEnumerable<string> files);
}

/// <summary>
/// 附件及文件操作类服务
/// 字符串作为主键的默认实现
/// </summary>
/// <typeparam name="TDbContext">数据库上下文</typeparam>
public interface IAttachmentService<TDbContext> :
    IAttachmentService<TDbContext, Attachment, string>
    where TDbContext : DbContext
{ }